/************************************************
 * Author       :   XXY
 * Blog         :   https://www.cnblogs.com/jzyl
 * Gitee        :   https://gitee.com/xiaobaichong
 * Email        :   1047185209@QQ.com
 * FileName     :   ComponetUtility.cs
 * CreateData   :   2023/5/13 11:36:17
 * UnityVersion :   2021.3.20f1c1
 * Description  :   组件工具类
************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Main;
using System;
using System.Reflection;

namespace Hotfix
{
    /// <summary>
    /// <para>组件工具类</para>
    /// </summary>
    internal static class ComponentUtility
    {
        /// <summary>
        /// 创建一个组件，并使用ComponentIDE 数据 初始化
        /// </summary>
        /// <typeparam name="T">要创建的组件类型</typeparam>
        /// <param name="data">数据</param>
        /// <returns></returns>
        public static T CreateComponent<T>(ComponentIDE data) where T : ComponentBase
        {
            T obj = Utility.CreateInstance<T>();
            Type type = obj.GetType();
            Type objType = typeof(UnityEngine.Object);
            List<string> fileds = new List<string>();
            foreach (var item in data.valueItems)
            {
                fileds.Add(item.FieldName);
            }
            foreach (var item in data.referenceItems)
            {
                fileds.Add(item.FieldName);
            }
            foreach (var item in data.valueCollectionItems)
            {
                fileds.Add(item.FieldName);
            }
            foreach (var item in data.referenceCollectionItems)
            {
                fileds.Add(item.FieldName);
            }
            foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
            {
                Type filedType = field.FieldType;
                string name = field.Name;
                if (fileds.Contains(name))
                {
                    // 集合类型
                    if (filedType.IsGenericType)
                    {
                        if (filedType.GetGenericArguments()[0].IsSubclassOf(objType))
                        {
                            // Unity 对象集合
                            MethodInfo method = data.GetType().GetMethod("GetReferences").MakeGenericMethod(filedType.GetGenericArguments()[0]);
                            var value = method.Invoke(data, new object[] { name });
                            field.SetValue(obj, value);
                        }
                        else
                        {
                            // 一般类型集合
                            MethodInfo method = data.GetType().GetMethod("GetValues").MakeGenericMethod(filedType.GetGenericArguments()[0]);
                            field.SetValue(obj, method.Invoke(data, new object[] { name }));
                        }
                    }
                    // 非集合类型
                    else
                    {
                        if (filedType.IsSubclassOf(objType))
                        {
                            // Unity 对象
                            MethodInfo method = data.GetType().GetMethod("GetReference").MakeGenericMethod(filedType);
                            var value = method.Invoke(data, new object[] { name });
                            field.SetValue(obj, value);
                        }
                        else
                        {
                            // 一般类型
                            MethodInfo method = data.GetType().GetMethod("GetValue").MakeGenericMethod(filedType);
                            var value = method.Invoke(data, new object[] { name });
                            field.SetValue(obj, value);
                        }
                    }
                }
            }
            return obj;
        }
        /// <summary>
        /// 创建一个组件，并使用Variables 数据 初始化
        /// </summary>
        /// <typeparam name="T">要创建的组件类型</typeparam>
        /// <param name="data">数据</param>
        /// <returns></returns>
        public static T CreateComponent<T>(VariablesIDE data) where T : ComponentBase
        {
            T obj = Utility.CreateInstance<T>();
            Type type = obj.GetType();
            foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
            {
                string name = field.Name;
                field.SetValue(obj, data.Get(name));
            }
            return obj;
        }
    }
}